package com.example.scribe.backend;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Registry for managing expression and statement node handlers.
 * Uses Strategy pattern to delegate node processing to appropriate handlers.
 */
public final class NodeHandlerRegistry {
    private final Map<String, ExpressionNodeHandler> expressionHandlers = new HashMap<>();
    private final Map<String, StatementNodeHandler> statementHandlers = new HashMap<>();
    private final List<ExpressionNodeHandler> expressionHandlerChain = new ArrayList<>();
    private final List<StatementNodeHandler> statementHandlerChain = new ArrayList<>();

    /**
     * Register an expression node handler.
     * 
     * @param handler the handler to register
     */
    void registerExpressionHandler(ExpressionNodeHandler handler) {
        if (handler == null) return;
        // Add to chain for fallback search
        expressionHandlerChain.add(handler);
        // Also index by node types that this handler can process
        // Note: This is a simplified version. In practice, you might want to
        // register handlers by specific node types they handle
    }

    /**
     * Register a statement node handler.
     * 
     * @param handler the handler to register
     */
    void registerStatementHandler(StatementNodeHandler handler) {
        if (handler == null) return;
        statementHandlerChain.add(handler);
    }

    /**
     * Register an expression handler for a specific node type.
     * 
     * @param nodeType the node type this handler handles
     * @param handler the handler to register
     */
    void registerExpressionHandler(String nodeType, ExpressionNodeHandler handler) {
        if (nodeType == null || handler == null) return;
        expressionHandlers.put(nodeType, handler);
        // Also add to chain if not already present
        if (!expressionHandlerChain.contains(handler)) {
            expressionHandlerChain.add(handler);
        }
    }

    /**
     * Register a statement handler for a specific node type.
     * 
     * @param nodeType the node type this handler handles
     * @param handler the handler to register
     */
    void registerStatementHandler(String nodeType, StatementNodeHandler handler) {
        if (nodeType == null || handler == null) return;
        statementHandlers.put(nodeType, handler);
        // Also add to chain if not already present
        if (!statementHandlerChain.contains(handler)) {
            statementHandlerChain.add(handler);
        }
    }

    /**
     * Get an expression handler for the given node type.
     * First checks direct mapping, then falls back to chain search.
     * 
     * @param nodeType the type of node to handle
     * @return the handler, or null if not found
     */
    ExpressionNodeHandler getExpressionHandler(String nodeType) {
        // First try direct lookup
        ExpressionNodeHandler handler = expressionHandlers.get(nodeType);
        if (handler != null) return handler;

        // Fall back to chain search
        for (ExpressionNodeHandler h : expressionHandlerChain) {
            if (h.canHandle(nodeType)) {
                return h;
            }
        }
        return null;
    }

    /**
     * Get a statement handler for the given node type.
     * First checks direct mapping, then falls back to chain search.
     * 
     * @param nodeType the type of node to handle
     * @return the handler, or null if not found
     */
    public StatementNodeHandler getStatementHandler(String nodeType) {
        // First try direct lookup
        StatementNodeHandler handler = statementHandlers.get(nodeType);
        if (handler != null) return handler;

        // Fall back to chain search
        for (StatementNodeHandler h : statementHandlerChain) {
            if (h.canHandle(nodeType)) {
                return h;
            }
        }
        return null;
    }

    /**
     * Create a default registry with all standard handlers.
     * 
     * @return a configured registry instance
     */
    static NodeHandlerRegistry createDefault() {
        NodeHandlerRegistry registry = new NodeHandlerRegistry();
        // Handlers will be registered as they are created
        // This method can be expanded when handlers are implemented
        return registry;
    }
}

